package org.xlx.xlx_oa.reimburse.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.xlx.xlx_oa.attendance.domain.AttendanceApply;
import org.xlx.xlx_oa.common.BusinessException;
import org.xlx.xlx_oa.common.Constant;
import org.xlx.xlx_oa.common.enums.ProcessStatusEnums;
import org.xlx.xlx_oa.common.enums.ProcessTypeEnums;
import org.xlx.xlx_oa.reimburse.convertor.ReimburseConvertor;
import org.xlx.xlx_oa.reimburse.domain.Reimburse;
import org.xlx.xlx_oa.reimburse.domain.ReimburseImage;
import org.xlx.xlx_oa.reimburse.domain.ReimburseItem;
import org.xlx.xlx_oa.reimburse.domain.dto.ReimburseDto;
import org.xlx.xlx_oa.reimburse.domain.dto.ReimburseImageDto;
import org.xlx.xlx_oa.reimburse.domain.dto.ReimburseItemDto;
import org.xlx.xlx_oa.reimburse.domain.vo.ReimburseItemVo;
import org.xlx.xlx_oa.reimburse.domain.vo.ReimburseVo;
import org.xlx.xlx_oa.reimburse.mapper.ReimburseMapper;
import org.xlx.xlx_oa.role_user.domain.AdmDepartment;
import org.xlx.xlx_oa.role_user.domain.AdmPosition;
import org.xlx.xlx_oa.role_user.domain.AdmProcess;
import org.xlx.xlx_oa.role_user.domain.AdmUser;
import org.xlx.xlx_oa.role_user.domain.dto.AdmProcessDto;
import org.xlx.xlx_oa.role_user.domain.vo.AuditVo;
import org.xlx.xlx_oa.role_user.mapper.AdmDepartmentMapper;
import org.xlx.xlx_oa.role_user.mapper.AdmPositionMapper;
import org.xlx.xlx_oa.role_user.mapper.AdmUserMapper;
import org.xlx.xlx_oa.role_user.service.AdmProcessService;
import org.xlx.xlx_oa.role_user.service.SysNotificationService;
import org.xlx.xlx_oa.utils.ThreadLocalUtil;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Service
public class ReimburseService {
    private final ReimburseConvertor reimburseConvertor = ReimburseConvertor.INSTANCE;
    private final ProcessTypeEnums processType = ProcessTypeEnums.Reimburse;
    @Autowired
    private ReimburseMapper reimburseMapper;
    @Autowired
    private ReimburseImageService imageService;
    @Autowired
    private ReimburseItemService itemService;
    @Autowired
    private AdmProcessService admProcessService;
    @Autowired
    private AdmUserMapper userMapper;
    @Autowired
    private AdmDepartmentMapper departmentMapper;
    @Autowired
    private AdmPositionMapper positionMapper;
    @Autowired
    private SysNotificationService notificationService;

    /**
     * 上传图片
     * @param files
     * @return
     * @throws Exception
     */
    public List<Long> uploadImage(MultipartFile[] files) throws Exception {
        ArrayList<String> urls = new ArrayList<>();
        for (MultipartFile file : files) {
            String upload = notificationService.upload(file);
            urls.add(upload);
        }
        ArrayList<Long> ids = new ArrayList<>();
        for (String url : urls) {
            Long id = imageService.uploadImage(url);
            ids.add(id);
        }
        return ids;
    }

    /**
     * 保存报销单
     */
    @Transactional
    public Boolean saveReimburse(ReimburseVo reimburseVo) {
        List<Long> imageIds = reimburseVo.getImageIds();
        if (imageIds.size()==0||imageIds==null){
            imageIds.add(0L);
        }
        List<ReimburseItemVo> itemVos = reimburseVo.getItemVos();
        List<ReimburseItem> items = new ArrayList<>();
        if (itemVos!=null){
            items = reimburseConvertor.convertVoToListItem(itemVos);
        }
        Long id = reimburseVo.getId();
        Reimburse domain = reimburseConvertor.convertVoToDomain(reimburseVo);
        if (id != null) {
            Reimburse reimburse = reimburseMapper.selectById(id);
            if (!ProcessStatusEnums.Pending.name().equals(reimburse.getProcessStatus())) {
                throw new BusinessException("100007", "The application is under review and cannot be modified");
            }
            reimburseMapper.updateById(reimburse);
        } else {
            reimburseMapper.insert(domain);
            items.forEach(item -> item.setReimburseId(domain.getId()));
            boolean flag = domain.getTotalAmount().compareTo(new BigDecimal("7200")) > -1;
            Boolean process = admProcessService.createProcess(domain.getId(), processType, flag);
            Reimburse reimburse = reimburseMapper.selectById(domain.getId());
            if (process) {
                reimburse.setProcessStatus(ProcessStatusEnums.Approve.name());
            } else {
                reimburse.setProcessStatus(ProcessStatusEnums.Processing.name());
            }
            reimburseMapper.updateById(reimburse);
        }
        imageService.matchImage(domain.getId(),imageIds);
        itemService.saveItems(domain.getId(),items);
        return true;
    }

    /**
     * 查询报销单申请列表
     */
    public List<ReimburseDto> getApplyList(ReimburseVo reimburseVo) {
        Integer pageNum = reimburseVo.getPageNum();
        Integer pageSize = reimburseVo.getPageSize();
        String status = reimburseVo.getProcessStatus();
        Object obj = ThreadLocalUtil.get(Constant.USERID);
        Long userId = (obj == null || "".equals(obj)) ? null : Long.valueOf(obj.toString());
        QueryWrapper<Reimburse> reimburseQueryWrapper = new QueryWrapper<>();
        Page<Reimburse> page = new Page<>(pageNum, pageSize);
        reimburseQueryWrapper.lambda()
                .eq(Reimburse::getCreatedId, userId);
        if (status != null && (!"".equals(status))) {
            reimburseQueryWrapper.lambda()
                    .eq(Reimburse::getProcessStatus, status);
        }
        reimburseMapper.selectPage(page, reimburseQueryWrapper);
        List<Reimburse> records = page.getRecords();
        List<ReimburseDto> reimburseDtos = reimburseConvertor.convertToDomainDtoList(records);
        reimburseDtos.forEach(reimburseDto -> this.supplyReimburseDto(reimburseDto));
        return reimburseDtos;
    }

    /**
     * 请求总数
     *
     * @param reimburseVo
     * @return
     */
    public Integer getApplyCount(ReimburseVo reimburseVo) {
        String status = reimburseVo.getProcessStatus();
        Object obj = ThreadLocalUtil.get(Constant.USERID);
        Long userId = (obj == null || "".equals(obj)) ? null : Long.valueOf(obj.toString());
        QueryWrapper<Reimburse> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(Reimburse::getCreatedId, userId);
        if (status != null && (!"".equals(status))) {
            wrapper.lambda()
                    .eq(Reimburse::getProcessStatus, status);
        }
        return reimburseMapper.selectCount(wrapper);
    }

    /**
     * 补全计划
     *
     * @param reimburseDto
     */
    public void supplyReimburseDto(ReimburseDto reimburseDto) {
        Long createdId = reimburseDto.getCreatedId();
        AdmUser user = userMapper.selectById(createdId);
        reimburseDto.setFirstName(user.getFirstName());
        reimburseDto.setMiddleName(user.getMiddleName());
        reimburseDto.setLastName(user.getLastName());
        if (user.getPositionId() != 0 && user.getPositionId() != null) {
            AdmPosition position = positionMapper.selectById(user.getPositionId());
            reimburseDto.setPositionTitle(position.getTitle());
        }
        if (user.getDepartmentId() != 0 && user.getDepartmentId() != null) {
            AdmDepartment admDepartment = departmentMapper.selectById(user.getDepartmentId());
            reimburseDto.setDepartmentTitle(admDepartment.getTitle());
        }
        ProcessStatusEnums statusEnums = ProcessStatusEnums.valueOf(ProcessStatusEnums.class, reimburseDto.getProcessStatus());
        reimburseDto.setProcessStatusName(statusEnums.getText());
        if (reimburseDto.getTackleStatus()!=null&&(!"".equals(reimburseDto.getTackleStatus()))){
            ProcessStatusEnums tackleEnums = ProcessStatusEnums.valueOf(ProcessStatusEnums.class, reimburseDto.getTackleStatus());
            reimburseDto.setTackleStatusName(tackleEnums.getText());
        }

        List<ReimburseImageDto> images = imageService.getImagesByApplyId(reimburseDto.getId());
        List<ReimburseItemDto> items = itemService.getItemsByApplyId(reimburseDto.getId());
        reimburseDto.setImages(images);
        reimburseDto.setItems(items);
    }

    /**
     * 查询报销单审批列表
     */
    public List<ReimburseDto> getBeAuditList(ReimburseVo reimburseVo) {
        Integer pageNum = reimburseVo.getPageNum();
        Integer pageSize = reimburseVo.getPageSize();
        List<AdmProcess> applyList = admProcessService.getApplyList(processType.name());
        HashMap<Long, String> map = new HashMap<>();
        if (applyList.size() == 0) {
            map.put(0L, "");
        } else {
            applyList.forEach(admProcess -> map.put(admProcess.getApplyId(), admProcess.getResult()));
        }
        Page<Reimburse> page = new Page<>(pageNum, pageSize);
        QueryWrapper<Reimburse> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .in(Reimburse::getId, map.keySet());
        if (reimburseVo.getProcessStatus() != null && (!"".equals(reimburseVo.getProcessStatus()))) {
            wrapper.lambda().eq(Reimburse::getProcessStatus, reimburseVo.getProcessStatus());
        }
        reimburseMapper.selectPage(page, wrapper);
        List<Reimburse> records = page.getRecords();
        List<ReimburseDto> reimburseDtos = reimburseConvertor.convertToDomainDtoList(records);
        reimburseDtos.forEach(reimburseDto -> {
            reimburseDto.setTackleStatus(map.get(reimburseDto.getId()));
            this.supplyReimburseDto(reimburseDto);
        });
        return reimburseDtos;
    }

    /**
     * 审批总数
     *
     * @param reimburseVo
     * @return
     */
    public Integer getBeAuditedCount(ReimburseVo reimburseVo) {
        String status = reimburseVo.getProcessStatus();
        List<AdmProcess> applyList = admProcessService.getApplyList(processType.name());
        HashMap<Long, String> map = new HashMap<>();
        if (applyList.size() == 0) {
            map.put(0L, "");
        } else {
            applyList.forEach(admProcess -> map.put(admProcess.getApplyId(), admProcess.getResult()));
        }
        QueryWrapper<Reimburse> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .in(Reimburse::getId, map.keySet());
        if (reimburseVo.getProcessStatus() != null && (!"".equals(reimburseVo.getProcessStatus()))) {
            wrapper.lambda().eq(Reimburse::getProcessStatus, reimburseVo.getProcessStatus());
        }
        return reimburseMapper.selectCount(wrapper);
    }

    /**
     * 审批详情
     *
     * @param applyId
     * @return
     */
    public List<AdmProcessDto> getApplyDetail(Long applyId) {
        return admProcessService.getListByApplyId(applyId, processType.name());
    }

    /**
     * 审批申请
     *
     * @param auditVo
     * @return
     */
    @Transactional
    public Boolean auditApply(AuditVo auditVo) {
        Reimburse reimburse = reimburseMapper.selectById(auditVo.getApplyId());
        String status = admProcessService.updateAuditProcess(auditVo, reimburse);
        reimburse.setProcessStatus(status);
        return reimburseMapper.updateById(reimburse) > 0;
    }

}
